// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Components/ActorComponent.h"
#include "GameFramework/GameplayMessageSubsystem.h"

#include "LyraDamageLogDebuggerComponent.generated.h"

namespace EEndPlayReason { enum Type : int; }

class UObject;
struct FGameplayTag;
struct FLyraVerbMessage;

/**
 * 单帧伤害记录条目结构体
 */
struct FFrameDamageEntry
{
	// 命中次数
	int32 NumImpacts = 0;
	// 总伤害值
	double SumDamage = 0.0;
	// 第一次命中的时间
	double TimeOfFirstHit = 0.0;
};

/**
 * 伤害日志调试器组件，用于记录和分析接收到的伤害。
 * 可生成并附加到Actor上。
 */
UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class ULyraDamageLogDebuggerComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	// 构造函数
	ULyraDamageLogDebuggerComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	/**
	 * 重写的UActorComponent函数。组件开始播放时调用，注册游戏消息监听器。
	 */
	virtual void BeginPlay() override;
	/**
	 * 重写的UActorComponent函数。组件结束播放时调用，注销游戏消息监听器。
	 */
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	/**
	 * 重写的UActorComponent函数。每帧调用，检查并记录伤害日志。
	 */
	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	// 在记录伤害日志之前，两次伤害之间需要间隔的秒数。
	UPROPERTY(EditAnywhere)
	double SecondsBetweenDamageBeforeLogging = 1.0;

private:
	// 游戏消息监听器句柄
	FGameplayMessageListenerHandle ListenerHandle;
	// 最后一次伤害记录条目的时间
	double LastDamageEntryTime = 0.0;
	// 伤害日志的映射表，键为帧计数器，值为伤害条目。
	TMap<int64, FFrameDamageEntry> DamageLog;

private:
	/**
	 * 当接收到伤害消息时调用的回调函数。
	 * @param Channel 消息频道（游戏标签）
	 * @param Payload 消息负载（包含伤害信息）
	 */
	void OnDamageMessage(FGameplayTag Channel, const FLyraVerbMessage& Payload);
};